
var lodash = require('lodash');

// handle 方法的处理成功码
const handleSuccessCode = {
	SUCCESS: "00", // 代表分页数据经过了处理并且成功了
	EMPTY_LIST: "01", // 空列表，根本没有处理
	OTHER: "99" //其他错误
}

/**
 * 分页工具，用于处理分页列表。
 * 目的为了增强代码复用性，减少重复、冗余代码。
 * 后续这个工具可能还会增强为通用的接口工具类， 不单是为了列表查询接口服务。
 */
class PageUtil  {

	_api = null;

    _config = {
        // 字段名
        field: {
            list: "list", // 列表数组的字段名
            paging: "paging", // 分页的字段名
            currPage: "curPageNO",
            pageSize: "pageSize"
        }
    };
    
    // 用于记录调用loadListByPage的参数，然后在loadListByPageMore时使用
    _paging = {
        vueThat: null,
        params: null, // 用来记住初次发起的请求参数, loadMore复用同样的参数查询下一页的数据
        options: null // 用来记录初次发起请求的options，loadMore复用同样的参数查询下一页的数据
    };

	constructor(api, config = {}){

        config = lodash.merge(this._config, config);
		this._api = api;
        this._config = config;
        
    }

    // handle 方法的处理成功码
	handleSuccessCode = handleSuccessCode;

	/**
	 * 加载列表，并进行分页处理（加载更多请调用 loadListByPageMore）
     * 此方法在页面进来时， 切换tab时， 切换查询条件时调用， 然后加载更多就调用 loadListByPageMore
	 * @param {*} vueThat vue的this 对象
	 * @param {*} params 调用接口所需的参数（选填，一般情况下传业务参数即可，比如页码和每页数量这些可以不传）
	 * @param {*} options 一些选项配置（选填），如下
     * {
            before: function(), // 调用接口前触发的 function
            listHandler: function(resultList), // 列表处理器，对接口返回的列表进行处理
            success: function(code, res), // 分页数据处理成功后触发的 function
            error: function(e), // 调用接口失败后触发的 function
            complete: function() // 调用接口完成后触发的 function，无论接口调用成功失败都会调用
        }
	 */
	loadListByPage(vueThat, params = {}, options = {}){
        
        // 默认选项
        let defaultOptions = {
            before: null, 
            success: null, 
            error: null, 
            complete: null,
            listHandler: null
        }

        options = lodash.merge(defaultOptions, options);

        // 执行前调用，如果调用者有传的话
		if(options.before){
			options.before();// 空参数调用
        }

        
        console.debug("vueThat: %o, params: %o, options: %o", params, vueThat, options);
        
        let that = this;
        
        // 获取vue页面data绑定的数据的字段名
        let listKey = that._config.field.list;
        let pagingKey = that._config.field.paging;

        // 获取分页查询参数的参数名
        let currPageKey = that._config.field.currPage;
        let pageSizeKey = that._config.field.pageSize;

        // 初始化分页数据
        if(!vueThat[pagingKey]){// 如果连paging都没定义
            vueThat[pagingKey] = {};
        }
        vueThat[pagingKey].tab = false;
        vueThat[pagingKey].currPage = 1;
        vueThat[pagingKey].pageSize = 10;
        vueThat[pagingKey].pageCount = 0;
        vueThat[pagingKey].total = 0;
        vueThat[pagingKey].loading = false;
        vueThat[pagingKey].finished = false;

        // 初始化列表数组
        vueThat[listKey] = [];
        
        // 处理请求参数 如果调用者没传
        if(!params[currPageKey]){
            params[currPageKey] = vueThat[pagingKey].currPage;
        }else{
            vueThat[pagingKey].currPage = params[currPageKey];
        }

        if(!params[pageSizeKey]){
            params[pageSizeKey] = vueThat[pagingKey].pageSize;
        }else{
            vueThat[pagingKey].pageSize = params[pageSizeKey];
        }
        
        // 初始化
        that._paging.vueThat = vueThat;
        that._paging.params = params;
        that._paging.options = options;

        // 处理分页数据
		_method.handlePage(this, vueThat, params, options);
    }
    
    /**
     * 在 loadListByPage 基础上加载下一页的列表数据
     */
    loadListByPageMore(options = {}){
        // 异步加载
        setTimeout(() => {
            
           
            let pagingKey = this._config.field.paging;

            let paging = this._paging;
            let vueThat = paging.vueThat;

             // TODO 用第一种还是用第二种？  暂定用第二种
            // if(!options || JSON.stringify(options) == "{}"){
            //     options = paging.options;
            // }

            options = lodash.merge(paging.options, options);

            // 执行前调用，如果调用者有传的话
            if(options.before){
                options.before();// 空参数调用
            }

            

            // total小于等于0说明是失败时的重试操作，调用刷新方法即可
            if(vueThat[pagingKey].total <= 0){
                this.loadListByPageRefresh();
                return;
            }

            //如果有超过要使他恢复最大
            if(vueThat[pagingKey].currPage > vueThat[pagingKey].pageCount){
                vueThat[pagingKey].currPage = vueThat[pagingKey].pageCount;
            }
            let currTotal = vueThat[pagingKey].currPage * vueThat[pagingKey].pageSize;
        
            if(currTotal >= vueThat[pagingKey].total){// 代表没有更多
                vueThat[pagingKey].loading = false;
                vueThat[pagingKey].finished = true;
                return;
            }
    
            // 找到原来的参数的页面参数，进行加1， 查询下一页数据
            let currPageKey = this._config.field.currPage;
            let params = paging.params;
            params[currPageKey] = vueThat[pagingKey].currPage + 1;//页码参数+1

            _method.handlePage(this, vueThat, params, options);
        }, 500);
    }

    /**
     * 刷新当前数据
     */
    loadListByPageRefresh(){
        let paging = this._paging;
        let vueThat = paging.vueThat;
        let params = paging.params;
        let options = paging.options;
        _method.handlePage(this, vueThat, params, options);
    }
}

// 一些私有，仅供内部调用的方法
const _method = {

    /**
     * 处理分页数据
     * @param {*} vueThat vue的this对象， 用于改变调用此方法的页面数据
     * @param {*} params 请求参数
     * @param {*} options 一些选项配置，参见 loadListByPage 方法的options参数描述
     */
    handlePage(pageUtil, vueThat, params, options){

        let pagingKey = pageUtil._config.field.paging;
        let listKey = pageUtil._config.field.list;

        pageUtil._api(params).then(res => {
            console.debug("接口调用结果：%o", res);

            let code = handleSuccessCode.SUCCESS;
    
            if(res.status == 1){

                vueThat[pagingKey].currPage = res.result.currPage;
                vueThat[pagingKey].pageSize = res.result.pageSize;
                vueThat[pagingKey].pageCount = res.result.pageCount;
                vueThat[pagingKey].total = res.result.total;
                
                if(res.result.resultList){
                    if(options.listHandler){
                        res.result.resultList = options.listHandler(res.result.resultList);
                    }
                
                    if(res.result.currPage == 1){//当页码是第一页时，直接赋值
                        vueThat[listKey] = res.result.resultList;
                    }else{// 否则追加
						vueThat[listKey].push(...res.result.resultList)
                    }
                }else{
                    code = handleSuccessCode.EMPTY_LIST;
                }

                // if(!vueThat[listKey] || !vueThat[listKey].length){
                //     vueThat[pagingKey].emptylist = true;
                // }else{
                //     vueThat[pagingKey].emptylist = false;
                // }
                
            }else{

                // 弹出消息提示是否合理？还是让调用者自己处理这种情况？
                vueThat.$toast({duration: 1000, message:res.msg});
    
                code = handleSuccessCode.OTHER;
            }
    
            if(options.success){
                options.success(code, res);
            }
    
        }).catch(e => {
            console.debug("接口调用异常：%o", e);

            vueThat[pagingKey].error = true;

            if(options.error){
                options.error(e);
            }
        }).finally(res => {
			if (!vueThat[listKey] || !vueThat[listKey].length) {
				vueThat[pagingKey].emptylist = true
			} else {
				vueThat[pagingKey].emptylist = false
			}
			
            vueThat[pagingKey].tab = true;
            vueThat[pagingKey].loading = false;
            
            if(options.complete){
                options.complete(res);
            }
        });
    }
}

export default PageUtil;